package com.pearl.generator.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.generator.IDatabaseQuery;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.IDbQuery;
import com.baomidou.mybatisplus.generator.config.ITypeConvert;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.querys.DbQueryDecorator;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.jdbc.DatabaseMetaDataWrapper;
import com.pearl.generator.common.BusinessException;
import com.pearl.generator.common.enums.YesOrNo;
import com.pearl.generator.pojo.PearlFiledInfo;
import com.pearl.generator.pojo.PearlTableInfo;
import com.pearl.generator.pojo.entity.DataSourceEntity;
import com.pearl.generator.mapper.DataSourceMapper;
import com.pearl.generator.pojo.vo.SimpleTableVO;
import com.pearl.generator.service.IDataSourceService;
import org.springframework.stereotype.Service;

import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author TangDan
 * @since 2022-07-07
 */
@Service
public class DataSourceServiceImpl extends ServiceImpl<DataSourceMapper, DataSourceEntity> implements IDataSourceService {
    public boolean testDbOnline(String url, String username, String password) {
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(url, username, password).build();
        try {
            new DbQueryDecorator(dataSourceConfig, null);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new BusinessException(StrUtil.format("连接失败，原因：{}", ex.getMessage()));
        }
        return true;
    }

    @Override
    public List<SimpleTableVO> tableInfoList(Long dataSourceId) {
        DataSourceEntity dataSource = getById(dataSourceId);
        List<SimpleTableVO> tableList = new ArrayList<>();
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword()).build();
        DbType dbType = dataSourceConfig.getDbType();
        DbQueryDecorator dbQueryDecorator = new DbQueryDecorator(dataSourceConfig, null);
        IDbQuery dbQuery = dataSourceConfig.getDbQuery();
        String tablesSql = dbQuery.tablesSql();
        String schemaName = dataSourceConfig.getSchemaName();
        if (DbType.POSTGRE_SQL == dbType || DbType.KINGBASE_ES == dbType || DbType.DB2 == dbType || DbType.ORACLE == dbType) {
            tablesSql = String.format(tablesSql, schemaName);
        }
        try {
            dbQueryDecorator.execute(tablesSql, (result) -> {
                String tableName = result.getStringResult(dbQueryDecorator.tableName());
                if (StringUtils.isNotBlank(tableName)) {

                    SimpleTableVO simpleTableVO = new SimpleTableVO();
                    simpleTableVO.setTableName(tableName);
                    String tableComment = result.getTableComment();
                    simpleTableVO.setTableComment(tableComment);
                    tableList.add(simpleTableVO);
                }
            });

            // tableList.forEach(this::convertTableFields);
        } catch (SQLException var12) {
            throw new RuntimeException(var12);
        } finally {
            dbQueryDecorator.closeConnection();
        }
        return tableList;
    }

    @Override
    public List<PearlFiledInfo> tableFiledInfo(String tableName, Long id) {
        DataSourceEntity dataSource = getById(id);
        List<PearlFiledInfo> filedInfoList = new ArrayList<>();
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword()).build();
        DbType dbType = dataSourceConfig.getDbType();
        DbQueryDecorator dbQueryDecorator = new DbQueryDecorator(dataSourceConfig, null);
        IDbQuery dbQuery = dataSourceConfig.getDbQuery();
        String tablesSql = dbQuery.tablesSql();
        String schemaName = dataSourceConfig.getSchemaName();
        if (DbType.POSTGRE_SQL == dbType || DbType.KINGBASE_ES == dbType || DbType.DB2 == dbType || DbType.ORACLE == dbType) {
            tablesSql = String.format(tablesSql, schemaName);
        }
        try {
            // tableList.forEach(this::convertTableFields);
            try {
                // 查询所有列信息
                Map<String, DatabaseMetaDataWrapper.ColumnsInfo> columnsMetaInfoMap = new HashMap();
                Map<String, DatabaseMetaDataWrapper.ColumnsInfo> columnsInfo = (new DatabaseMetaDataWrapper(dbQueryDecorator.getConnection())).getColumnsInfo((String) null,
                        dataSourceConfig.getSchemaName(), tableName);
                if (columnsInfo != null && !columnsInfo.isEmpty()) {
                    columnsMetaInfoMap.putAll(columnsInfo);
                }
                String tableFieldsSql = dbQueryDecorator.tableFieldsSql(tableName);
                Set<String> h2PkColumns = new HashSet();
                if (DbType.H2 == dbType) {
                    dbQueryDecorator.execute(String.format("select * from INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME = '%s'", tableName), (result) -> {
                        String primaryKey = result.getStringResult(dbQueryDecorator.fieldKey());
                        if (Boolean.parseBoolean(primaryKey)) {
                            h2PkColumns.add(result.getStringResult(dbQueryDecorator.fieldName()));
                        }

                    });
                }
                dbQueryDecorator.execute(tableFieldsSql, (result) -> {
                    PearlFiledInfo filedInfo = new PearlFiledInfo();
                    String columnName = result.getStringResult(dbQueryDecorator.fieldName()); // 列名
                    filedInfo.setName(columnName);
                    boolean isId = DbType.H2 == dbType ? h2PkColumns.contains(columnName) : result.isPrimaryKey();
                    if (isId) {
                        boolean keyIdentity = dbQueryDecorator.isKeyIdentity(result.getResultSet()); // 是否主键
                        filedInfo.setIsId(YesOrNo.Yes.getValue());
                    }
                    String type = result.getStringResult(dbQueryDecorator.fieldType());// 字段类型
                    filedInfo.setType(type);
                    String filedComment = result.getFiledComment();// 字段注释
                    filedInfo.setComment(filedComment);
                    filedInfoList.add(filedInfo);
                });
            } catch (SQLException var9) {
                throw new RuntimeException(var9);
            }
        } catch (Exception var12) {
            throw new RuntimeException(var12);
        } finally {
            dbQueryDecorator.closeConnection();
        }
        return filedInfoList;
    }


}
